#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_CODE_LEN	100000
#define MAX_DATA_LEN	100000
#define MAX_STACK_SIZE	10000
#define MAX_NAME_LEN	128
#define MAX_FUNC_NUM	64
#define PUSH(x)	ss[esp++]=(x)
#define POP		(ss[--esp])


typedef unsigned char	uint8_t;
typedef unsigned int	uint32_t;

// 保存过程属性.
struct Function {
	char name[MAX_NAME_LEN];
	uint32_t start;
	uint32_t end;
	struct Function *next;
};

char code[MAX_CODE_LEN];
uint8_t data[MAX_DATA_LEN];
uint32_t di;
uint32_t ss[MAX_STACK_SIZE], esp;
struct Function *functions[MAX_FUNC_NUM];

// 函数声明.
void interpret(uint32_t ci);

// 忽略无意义字符.
void
ignore(uint32_t *pci)
{
	while (!strchr(":<>=+-.,[]0123456789{#}",code[*pci])) {
		(*pci)++;
	}
}
// 得到重复度n.
uint32_t
dup(uint32_t *pci)
{
	uint32_t n=1;
	//ignore(pci);
	if (isdigit(code[*pci])) {
		n=atoi(&code[*pci]);
		while (isdigit(code[*pci])) {
			(*pci)++;
		}
	}
	return n;
}

// 得到字符串对应的hash值.
uint32_t
hash(char *s)
{
	uint32_t h=0;
	char *ps=s;
	while (*ps) {
		h+=*ps++;
	}
	return h%MAX_FUNC_NUM;
}

// 函数详情.
void
function_dump(struct Function *func)
{
	printf("func name:\n\t%s\n",func->name);
	code[func->end]='\0';
	printf("func content:\n\t%s\n",&code[func->start]);
	code[func->end]='}';
}
// 注册函数.
void
function_reg(struct Function *func)
{
	uint32_t fid=hash(func->name);
	struct Function **ffunc=&functions[fid];
	if (*ffunc) {
		while ((*ffunc)->next) {
			*ffunc=(*ffunc)->next;
		}
		(*ffunc)->next=func;
		return;
	}
	functions[fid]=func;
	return;
}

// functions...
void
function(uint32_t *pci)
{
	uint32_t name_start,name_len;
	uint32_t func_start,func_end;
	struct Function *func;
	if (code[*pci]=='#') {
		name_start=++(*pci);
		while (code[*pci]!='#') {
			(*pci)++;
		}
		name_len=((*pci)++)-name_start;

		ignore(pci);
		func_start=*pci;
		while (code[*pci]!='}') {
			(*pci)++;
		}
		func_end=(*pci)++;

		// filling a function struct...
		func=(struct Function *)malloc(sizeof(struct Function));
		strncpy(func->name,&code[name_start],name_len);
		func->name[name_len]='\0';
		func->start=func_start;
		func->end=func_end;
		func->next=NULL;

		// register the function...
		function_reg(func);
	}
}
// 得到函数指针.
struct Function *
function_fetch(char *name)
{
	uint32_t fid=hash(name);
	struct Function *func=functions[fid];
	while (func&&strcmp(func->name,name)) {
		func=func->next;
	}
	return func;
}
// 调用函数.
function_call(uint32_t *pci)
{
	uint32_t name_start,name_len;
	uint32_t func_start,func_end;
	uint32_t fid,i;
	struct Function *func;
	char func_name[MAX_NAME_LEN];
	name_start=*pci;
	while (code[*pci]!='#') {
		(*pci)++;
	}
	name_len=((*pci)++)-name_start;
	strncpy(func_name,&code[name_start],name_len);
	func_name[name_len]='\0';

	func=function_fetch(func_name);
	if (func) {
		PUSH(*pci);
		interpret(func->start);
		*pci=POP;
	}

}
// 主解释程序.
void
interpret(uint32_t ci)
{
	uint32_t b, n, i;
	uint32_t wi;

	while (code[ci]) {
		switch (code[ci++]) {
			case ':':
				n=dup(&ci);
				di=n;
				break;
			case '<':
				n=dup(&ci);
				di-=n;
				break;
			case '>':
				n=dup(&ci);
				di+=n;
				break;
			case '=':
				n=dup(&ci);
				data[di]=n;
				break;
			case '+':
				n=dup(&ci);
				data[di]+=n;
				break;
			case '-':
				n=dup(&ci);
				data[di]-=n;
				break;
			case '{':
				function(&ci);
				break;
			case '#':
				function_call(&ci);
				break;
			case '}':
				return;
			case '.':
				n=dup(&ci);
				for (i=0; i<n; i++) {
					putchar(data[di+i]);//fflush(stdout);
				}
				break;
			case ',':
				n=dup(&ci);
				for (i=0; i<n; i++) {
					data[di+i]=getchar();//fflush(stdout);
				}
				break;
			case '[':
				for (b=1,wi=ci;b&&code[ci];ci++)
					b+=code[ci]=='[',b-=code[ci]==']';
				if (!b) {
					while (data[di])
						interpret(wi);
					break;
				}
				printf("unbalanced brackets!");
				exit(0);
			case ']':
				return;
			default:
				break;
		}
		if (di<0||di>=5000)
			puts("data index off the range."),exit(0);
	}
}

int
main(int argc, char *argv[])
{
	FILE *fin;
	char *s=code,ch;

	if (fin=fopen(argv[1],"r")) {
		while ((ch=getc(fin))>=0)
			*s++=ch;
		fclose(fin);
		*s=0;
		interpret(0);
	}
	return 0;
}
